package com.dms.modules.community.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dms.common.security.SecurityUtils;
import com.dms.modules.community.dto.CommunityCommentDTO;
import com.dms.modules.community.dto.CommunityCommentDetailDTO;
import com.dms.modules.community.dto.CommunityCommentTreeDTO;
import com.dms.modules.community.entity.CommunityComment;
import com.dms.modules.community.entity.CommunityCommentLike;
import com.dms.modules.community.entity.CommunityPost;
import com.dms.modules.community.entity.CommunityLike;
import com.dms.modules.community.mapper.CommunityCommentMapper;
import com.dms.modules.community.mapper.CommunityCommentLikeMapper;
import com.dms.modules.community.mapper.CommunityPostMapper;
import com.dms.modules.community.mapper.CommunityLikeMapper;
import com.dms.modules.community.service.CommunityCommentService;
import com.dms.modules.message.dto.CommunityNotificationDTO;
import com.dms.modules.message.dto.MessageDetailDTO;
import com.dms.modules.message.websocket.MessageWebSocket;
import com.dms.modules.user.service.UserCenterService;
import com.dms.modules.user.vo.UserInfoVO;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CommunityCommentServiceImpl extends ServiceImpl<CommunityCommentMapper, CommunityComment> implements CommunityCommentService {

    private final Gson gson = new Gson();

    @Autowired
    private CommunityCommentLikeMapper commentLikeMapper;

    @Autowired
    private CommunityPostMapper postMapper;

    @Autowired
    private MessageWebSocket messageWebSocket;

    @Autowired
    private UserCenterService userCenterService;

    @Autowired
    private CommunityLikeMapper likeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createComment(CommunityCommentDTO commentDTO) {
        try {
            // 1. 创建评论
            CommunityComment comment = new CommunityComment();
            comment.setPostId(commentDTO.getPostId());
            comment.setUserId(commentDTO.getUserId());
            comment.setParentId(commentDTO.getParentId());
            comment.setContent(commentDTO.getContent());
            comment.setLikeCount(0);
            comment.setStatus(0);
            comment.setCreateTime(LocalDateTime.now());
            save(comment);

            // 2. 更新帖子评论数
            LambdaUpdateWrapper<CommunityPost> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(CommunityPost::getId, commentDTO.getPostId())
                    .setSql("comment_count = comment_count + 1");
            postMapper.update(null, updateWrapper);

            // 3. 发送通知
            sendCommentNotification(commentDTO.getUserId(), commentDTO.getPostId(), comment.getId());

            log.info("评论创建成功: userId={}, postId={}, commentId={}", 
                    commentDTO.getUserId(), commentDTO.getPostId(), comment.getId());
        } catch (Exception e) {
            log.error("评论创建失败: userId={}, postId={}, error={}", 
                    commentDTO.getUserId(), commentDTO.getPostId(), e.getMessage(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteComment(Long commentId) {
        try {
            CommunityComment comment = getById(commentId);
            if (comment == null) {
                log.warn("评论不存在: commentId={}", commentId);
                return;
            }
            
            removeById(commentId);
            log.info("评论删除成功: commentId={}", commentId);
        } catch (Exception e) {
            log.error("评论删除失败: commentId={}, error={}", commentId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void likeComment(Long commentId) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            
            // 1. 检查是否已点赞
            LambdaQueryWrapper<CommunityLike> likeWrapper = new LambdaQueryWrapper<>();
            likeWrapper.eq(CommunityLike::getUserId, userId)
                      .eq(CommunityLike::getTargetId, commentId)
                      .eq(CommunityLike::getTargetType, 2); // 2-评论
            if (likeMapper.selectCount(likeWrapper) > 0) {
                // 如果已点赞，则取消点赞
                likeMapper.delete(likeWrapper);
                
                // 更新评论点赞数
                LambdaUpdateWrapper<CommunityComment> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(CommunityComment::getId, commentId)
                           .setSql("like_count = like_count - 1");
                update(null, updateWrapper);
                
                log.info("取消点赞成功: userId={}, commentId={}", userId, commentId);
            } else {
                // 如果未点赞，则添加点赞
                CommunityLike like = new CommunityLike();
                like.setUserId(userId);
                like.setTargetId(commentId);
                like.setTargetType(2); // 2-评论
                like.setCreateTime(LocalDateTime.now());
                likeMapper.insert(like);

                // 更新评论点赞数
                LambdaUpdateWrapper<CommunityComment> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(CommunityComment::getId, commentId)
                           .setSql("like_count = like_count + 1");
                update(null, updateWrapper);
                
                log.info("点赞成功: userId={}, commentId={}", userId, commentId);
            }
        } catch (Exception e) {
            log.error("评论点赞操作失败: commentId={}, error={}", commentId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public IPage<CommunityCommentDetailDTO> getPostComments(Long postId, Page<CommunityCommentDetailDTO> page) {
        // 只查询顶级评论
        LambdaQueryWrapper<CommunityComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CommunityComment::getPostId, postId)
               .isNull(CommunityComment::getParentId)
               .orderByDesc(CommunityComment::getCreateTime);
        
        IPage<CommunityComment> commentPage = page(new Page<>(page.getCurrent(), page.getSize()), wrapper);
        
        // 转换为DetailDTO
        List<CommunityCommentDetailDTO> records = commentPage.getRecords().stream()
                .map(this::convertToDetailDTO)
                .collect(Collectors.toList());
        
        // 查询子评论
        records.forEach(this::setChildComments);
        
        // 构建返回结果
        IPage<CommunityCommentDetailDTO> result = new Page<>(commentPage.getCurrent(), commentPage.getSize(), commentPage.getTotal());
        result.setRecords(records);
        return result;
    }

    @Override
    public IPage<CommunityCommentTreeDTO> getCommentList(Long postId, Long currentUserId, Page<CommunityCommentTreeDTO> page) {
        try {
            // 1. 查询一级评论
            LambdaQueryWrapper<CommunityComment> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CommunityComment::getPostId, postId)
                  .eq(CommunityComment::getDeleted, 0)
                  .isNull(CommunityComment::getParentId)  // 只查询一级评论
                  .orderByDesc(CommunityComment::getCreateTime);

            IPage<CommunityComment> commentPage = page(new Page<>(page.getCurrent(), page.getSize()), wrapper);

            // 2. 转换为DTO并设置额外信息
            return commentPage.convert(comment -> {
                CommunityCommentTreeDTO dto = convertToTreeDTO(comment, currentUserId);
                
                // 查询子评论数量
                LambdaQueryWrapper<CommunityComment> replyWrapper = new LambdaQueryWrapper<>();
                replyWrapper.eq(CommunityComment::getParentId, comment.getId())
                          .eq(CommunityComment::getDeleted, 0);
                Long replyCount = count(replyWrapper);
                dto.setReplyCount(replyCount.intValue());
                
                // 初始化空的子评论列表
                dto.setChildren(new ArrayList<>());
                
                return dto;
            });
        } catch (Exception e) {
            log.error("获取评论列表失败: postId={}, error={}", postId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public List<CommunityCommentTreeDTO> getCommentReplies(Long commentId, Long currentUserId) {
        try {
            // 1. 查询子评论
            LambdaQueryWrapper<CommunityComment> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CommunityComment::getParentId, commentId)
                  .eq(CommunityComment::getDeleted, 0)
                  .orderByAsc(CommunityComment::getCreateTime);

            List<CommunityComment> replies = list(wrapper);

            // 2. 转换为DTO并设置额外信息
            return replies.stream()
                .map(reply -> {
                    CommunityCommentTreeDTO dto = convertToTreeDTO(reply, currentUserId);
                    dto.setChildren(new ArrayList<>()); // 初始化空的子评论列表
                    return dto;
                })
                .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取评论回复失败: commentId={}, error={}", commentId, e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public List<CommunityCommentTreeDTO> getAllCommentReplies(Long postId, List<Long> commentIds, Long currentUserId) {
        try {
            if (commentIds == null || commentIds.isEmpty()) {
                return new ArrayList<>();
            }

            // 1. 查询所有直接回复
            LambdaQueryWrapper<CommunityComment> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CommunityComment::getPostId, postId)
                  .eq(CommunityComment::getDeleted, 0)
                  .in(CommunityComment::getParentId, commentIds)
                  .orderByAsc(CommunityComment::getCreateTime);

            List<CommunityComment> directReplies = list(wrapper);
            
            // 2. 递归查询子回复
            List<CommunityComment> allReplies = new ArrayList<>(directReplies);
            List<Long> replyIds = directReplies.stream()
                .map(CommunityComment::getId)
                .collect(Collectors.toList());
            
            while (!replyIds.isEmpty()) {
                wrapper.clear();
                wrapper.eq(CommunityComment::getPostId, postId)
                      .eq(CommunityComment::getDeleted, 0)
                      .in(CommunityComment::getParentId, replyIds)
                      .orderByAsc(CommunityComment::getCreateTime);
                
                List<CommunityComment> subReplies = list(wrapper);
                if (subReplies.isEmpty()) {
                    break;
                }
                
                allReplies.addAll(subReplies);
                replyIds = subReplies.stream()
                    .map(CommunityComment::getId)
                    .collect(Collectors.toList());
            }

            // 3. 转换为DTO
            return allReplies.stream()
                .map(reply -> convertToTreeDTO(reply, currentUserId))
                .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取评论回复失败: postId={}, commentIds={}, error={}", 
                    postId, commentIds, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 将评论实体转换为树状DTO
     */
    private CommunityCommentTreeDTO convertToTreeDTO(CommunityComment comment, Long currentUserId) {
        CommunityCommentTreeDTO dto = new CommunityCommentTreeDTO();
        BeanUtils.copyProperties(comment, dto);
        
        try {
            // 设置用户信息
            UserInfoVO userInfo = userCenterService.getUserInfo(comment.getUserId());
            if (userInfo != null) {
                dto.setUserNickname(userInfo.getNickname());
                dto.setUserAvatar(userInfo.getAvatar());
            } else {
                dto.setUserNickname("用户" + comment.getUserId());
                dto.setUserAvatar("/static/images/default-avatar.jpg");
            }
        } catch (Exception e) {
            log.warn("获取评论用户信息失败: userId={}, error={}", comment.getUserId(), e.getMessage());
            dto.setUserNickname("用户" + comment.getUserId());
            dto.setUserAvatar("/static/images/default-avatar.jpg");
        }

        // 设置点赞状态
        if (currentUserId != null) {
            try {
                LambdaQueryWrapper<CommunityLike> likeWrapper = new LambdaQueryWrapper<>();
                likeWrapper.eq(CommunityLike::getUserId, currentUserId)
                          .eq(CommunityLike::getTargetId, comment.getId())
                          .eq(CommunityLike::getTargetType, 2); // 2-评论
                dto.setIsLiked(likeMapper.selectCount(likeWrapper) > 0);
            } catch (Exception e) {
                log.warn("获取评论点赞状态失败: commentId={}, userId={}, error={}", 
                        comment.getId(), currentUserId, e.getMessage());
                dto.setIsLiked(false);
            }
        } else {
            dto.setIsLiked(false);
        }

        return dto;
    }

    private CommunityCommentDetailDTO convertToDetailDTO(CommunityComment comment) {
        CommunityCommentDetailDTO detailDTO = new CommunityCommentDetailDTO();
        BeanUtils.copyProperties(comment, detailDTO);
        // TODO: 设置用户信息、点赞状态等
        return detailDTO;
    }

    private void setChildComments(CommunityCommentDetailDTO parentDTO) {
        LambdaQueryWrapper<CommunityComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CommunityComment::getParentId, parentDTO.getId())
               .orderByAsc(CommunityComment::getCreateTime);
        
        List<CommunityComment> children = list(wrapper);
        List<CommunityCommentDetailDTO> childrenDTO = children.stream()
                .map(this::convertToDetailDTO)
                .collect(Collectors.toList());
        
        parentDTO.setChildren(childrenDTO);
    }

    private void sendCommentNotification(Long userId, Long postId, Long commentId) {
        try {
            // 1. 获取用户信息
            UserInfoVO userInfo = userCenterService.getUserInfo(userId);
            if (userInfo == null) {
                log.warn("用户不存在: userId={}", userId);
                return;
            }

            // 2. 获取帖子信息
            CommunityPost post = postMapper.selectById(postId);
            if (post == null) {
                log.warn("帖子不存在: postId={}", postId);
                return;
            }

            // 3. 构建通知消息
            CommunityNotificationDTO notification = new CommunityNotificationDTO();
            notification.setType(3); // 3-评论通知
            notification.setOperatorId(userId);
            notification.setOperatorNickname(userInfo.getNickname());
            notification.setOperatorAvatar(userInfo.getAvatar());
            notification.setPostId(postId);
            notification.setPostTitle(post.getTitle());
            notification.setCommentId(commentId);
            notification.setCreateTime(LocalDateTime.now());

            // 4. 发送WebSocket消息
            MessageDetailDTO message = new MessageDetailDTO();
            message.setType(1); // 1-系统通知
            message.setTitle("收到新的评论");
            message.setContent(gson.toJson(notification));
            message.setUserId(post.getUserId()); // 发送给帖子作者

            messageWebSocket.sendMessage(post.getUserId(), message);
        } catch (Exception e) {
            log.error("发送评论通知失败: userId={}, postId={}, commentId={}", userId, postId, commentId, e);
        }
    }
} 